/*
 * @Author: fantao.meng
 * @Date: 2018-08-20 16:57:10
 * @Last Modified by: fantao.meng
 * @Last Modified time: 2018-09-20 00:21:01
 */

import React from 'react';
import {
  View,
  Image,
  Animated,
  Easing,
  ViewPropTypes,
  StyleSheet,
  Platform,
  TouchableOpacity
} from 'react-native';
import * as PropTypes from 'prop-types';

export default class LoadImage extends React.Component {
  static propTypes = {
    style: PropTypes.oneOfType([ViewPropTypes.style, PropTypes.number]),
    source: PropTypes.oneOfType([PropTypes.object, PropTypes.number]),
    defaultSource: PropTypes.oneOfType([PropTypes.object, PropTypes.number]),
    onLoad: PropTypes.func,
    onError: PropTypes.func,
    onClick: PropTypes.func,
    type: PropTypes.oneOf(['animated', 'load']),
  };

  static defaultProps = {
    onLoad: () => {},
    onError: () => {},
    onClick: () => {},
    type: 'animated',
  };

  constructor(props) {
    super(props);
    this.state = {
      loadStatus: 'pending',
      backgroundColor: new Animated.Value(0),
    };
  }

  componentWillUnmount() {
    if (undefined !== this.backgroundColorAnimated) {
      this.backgroundColorAnimated.stop();
    }
  }

  /**
   * 图片资源开始加载
   */
  onLoadStart = () => {
    // 配置加载动画
    if (this.props.type !== 'animated') return;
    this.backgroundColorAnimated = Animated.sequence([
      Animated.timing(this.state.backgroundColor, {
        toValue: 1,
        easing: Easing.ease,
        duration: 800,
        useNativeDriver: false
      }),
      Animated.timing(this.state.backgroundColor, {
        toValue: 0,
        easing: Easing.in,
        duration: 800,
        useNativeDriver: false
      }),
    ]);
    // 开启循环动画
    this.backgroundColorAnimated.start(() => {
      this.state.loadStatus === 'pending' && this.onLoadStart();
    });
  };

  /**
   * 加载结束
   */
  onLoadEnd = () => {
    // if (undefined !== this.backgroundColorAnimated) this.backgroundColorAnimated.stop()
  };

  /**
   * 加载成功
   */
  handleImageLoaded = () => {
    this.setState({ loadStatus: 'success' }, () => {
      this.props.onLoad();
    });
  };

  /**
   * 加载失败
   * @param {*} error
   */
  handleImageErrored = (error) => {
    console.log(error);
    this.setState({ loadStatus: 'error' }, () => {
      this.props.onError();
    });
  };

  /**
   * 渲染加载中界面
   */
  renderPending = () => {
    const { style, type } = this.props;
    return type === 'animated' ? (
      <Animated.View
        style={[
          style,
          {
            position: 'absolute',
            backgroundColor: this.state.backgroundColor.interpolate({
              inputRange: [0, 0.5, 1],
              outputRange: ['#EBEBEB', '#F5F5F5', '#EBEBEB'],
            }),
            alignItems: 'center',
            justifyContent: 'center'
          },
        ]}
      >
        <Image
          style={{ width: style.width / 3, height: style.width / 3 }}
          source={require('./loading.gif')}
        />
      </Animated.View>
    ) : (
      <View
        style={[
          style,
          {
            position: 'absolute',
            justifyContent: 'center',
            alignItems: 'center',
            backgroundColor: '#eceff4',
          },
        ]}
      >
        <Image
          style={{ width: 30, height: 30 }}
          source={require('./loading-spinner.gif')}
        />
      </View>

    );
  };

  /**
   * 渲染加载失败界面
   */
  renderError = () => {
    let { style, defaultSource } = this.props;
    if (typeof style === 'number') {
      style = StyleSheet.flatten(style);
    }
    // const iconSize = Math.min(style.height, style.width) / 3;
    return defaultSource ? (
      <Image source={defaultSource} style={[{ position: 'absolute' }, style]} />
    ) : (
      // <View
      //   style={[
      //     {
      //       justifyContent: 'center',
      //       backgroundColor: '#eceff4',
      //       position: 'absolute',
      //       alignItems: 'center',
      //     },
      //     style,
      //   ]}
      // />
      <Image source={require('./pic_loading.png')} style={[{ position: 'absolute' }, style]} resizeMode='contain' />
    );
  };

  render() {
    let { style, source, onClick } = this.props;
    let { loadStatus } = this.state;
    // 兼容 uri为null的情况
    if (source.hasOwnProperty('uri') && typeof source.uri !== 'string') {
      source = { ...source, uri: '' };
    }
    // 兼容Androud无法对空字符串进行处理情况
    if (
      Platform.OS === 'android' &&
      source.hasOwnProperty('uri') &&
      !source.uri
    ) {
      source = { ...source, uri: ' ' };
    }
    return (
      <View style={[style, { overflow: 'hidden' }]}>
        <TouchableOpacity
          activeOpacity={0.8}
          onPress={() => {
            onClick(source);
          }}
          style={style}
        >
          <Image
            source={source}
            style={style}
            onLoadStart={this.onLoadStart}
            onLoadEnd={this.onLoadEnd}
            onLoad={this.handleImageLoaded}
            onError={this.handleImageErrored}
          />
        </TouchableOpacity>
        {loadStatus === 'pending' && this.renderPending()}
        {loadStatus === 'error' && this.renderError()}
      </View>
    );
  }
}
